package com.htcms.base;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.htcms.utils.Pager;

public class HibernateBaseDao extends HibernateDaoSupport {

	/**
	 * 根据主键加载对象
	 * 
	 * @param beanClass
	 * @param ident
	 * @return
	 */
	public Object getBean(Class beanClass, Serializable key) {
		// return getSession().get(beanClass, key);
		return this.getHibernateTemplate().get(beanClass, key);
	}

	/**
	 * 执行返回单一结果的查询语�?<b>调用者必须确保返回的结果只有�?��！！�?/b>
	 * 
	 * @param hql
	 * @param args
	 * @return
	 */
	public Object uniqueResult(String hql, Object... args) {
		Session ssn = getSession();
		Query q = ssn.createQuery(hql);
		for (int i = 0; i < args.length; i++) {
			q.setParameter(i, args[i]);
		}
		return q.uniqueResult();
	}

	/**
	 * 执行统计查询语句
	 * 
	 * @param hql
	 * @param args
	 * @return
	 */
	public Number executeStat(String hql, Object... args) {
		return (Number) uniqueResult(hql, args);
	}

	public int executeStatAsInt(String hql, Object... args) {
		Number num = executeStat(hql, args);
		if (num != null) {
			return num.intValue();
		}
		return 0;
	}

	public long executeStatAsLong(String hql, Object... args) {
		return executeStat(hql, args).longValue();
	}

	/**
	 * 执行普�?查询语句
	 * 
	 * @param hql
	 * @param args
	 * @return
	 */
	public List executeQuery(String hql, int fromIdx, int fetchCount,
			Object... args) {
		Session ssn = getSession();
		Query q = ssn.createQuery(hql);
		for (int i = 0; i < args.length; i++) {
			q.setParameter(i, args[i]);
		}
		if (fromIdx > 0)
			q.setFirstResult(fromIdx);
		if (fetchCount > 0)
			q.setMaxResults(fetchCount);
		return q.list();
	}

	/**
	 * 执行普�?查询语句
	 * 
	 * @param hql
	 * @param args
	 * @return
	 */
	public List findAll(String hql, Object... args) {
		return executeQuery(hql, -1, -1, args);
	}

	/**
	 * 执行普�?查询语句
	 * 
	 * @param hql
	 * @param fromIdx
	 * @param fetchCount
	 * @param args
	 * @return
	 */
	public List<?> templatQeuery(final String hql, final int fromIdx,
			final int fetchCount, final Object[] args) {
		try {
			return this.getHibernateTemplate().executeFind(
					new HibernateCallback() {
						public Object doInHibernate(Session session)
								throws HibernateException, SQLException {
							Query query = session.createQuery(hql);
							if (args != null)
								for (int i = 0; i < args.length; i++) {
									query.setParameter(i, args[i]);
								}
							if (fromIdx > 0)
								query.setFirstResult(fromIdx);
							if (fetchCount > 0)
								query.setMaxResults(fetchCount);
							return query.list();
						}
					});
		} catch (RuntimeException re) {
			logger.error("query failed!", re);
			throw re;
		}
	}

	/**
	 * Criteria
	 * 
	 * @param pager
	 *            �??分页�?
	 * @param className
	 *            查找的类(�?
	 * @param criterions
	 *            条件
	 * @param orders
	 *            排序
	 */
	protected void findPageByCriteria(Pager pager, Class className,
			List<Criterion> criterions, List<Order> orders) {
		Criteria criteria = this.getSession().createCriteria(className);
		if (null != criterions && criterions.size() > 0) {
			for (Criterion c : criterions) {
				criteria.add(c);
			}
		}
		int rowCount = (Integer) criteria.setProjection(Projections.rowCount())
				.uniqueResult();
		pager.setRowCount(rowCount);
		criteria.setProjection(null);
		criteria.setFirstResult((pager.getPageNo() - 1) * pager.getPageSize());
		if (pager.getPageSize() > 0)
			criteria.setMaxResults(pager.getPageSize());
		if (null != orders && orders.size() > 0) {
			for (Order o : orders) {
				criteria.addOrder(o);
			}
		}
		pager.setResult(criteria.list());
	}

	/**
	 * 计数
	 * 
	 * @param hql
	 * @param args
	 * @return
	 */
	public Integer getCount(String hql, Object[] args) {
		List<?> result = templatQeuery(hql, 0, 0, args);
		if (result == null || result.isEmpty()) {
			return 0;
		} else {
			return ((Number) result.get(0)).intValue();
		}
	}

	public void flush() {
		getHibernateTemplate().flush();
	}

	public void clear() {
		getHibernateTemplate().clear();
	}
}
